package com.bc004346.travelus.Fragment;

import android.app.Activity;
import android.content.res.Resources;
import android.graphics.Color;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.support.v4.app.Fragment;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.ProgressBar;
import android.widget.TextSwitcher;
import android.widget.TextView;
import android.widget.ViewSwitcher;

import com.bc004346.travelus.DataAccess.TravelUsScreenScraper;
import com.bc004346.travelus.Model.Domain.Flight;
import com.bc004346.travelus.Model.TravelUsException;
import com.bc004346.travelus.R;
import com.bc004346.travelus.Utility.Utility;

import java.util.Date;

import static com.bc004346.travelus.DataAccess.UsAirwaysScreenScraper.getFlightStatus;
import static com.bc004346.travelus.Utility.Utility.DAY_DATE;
import static com.bc004346.travelus.Utility.Utility.MILITARY_TIME;
import static com.bc004346.travelus.Utility.Utility.MINUTE;
import static com.bc004346.travelus.Utility.Utility.SECOND;
import static com.bc004346.travelus.Utility.Utility.log;

/**
 * Created by Renats on 9/8/2014.
 * Flight details fragment
 */
public class FlightDetailsFragment extends Fragment {

    //<editor-fold desc="Members">
    public static final String EXTRA_FLIGHT_ID =
            "com.bc004346.travelus.flightId";
    public static final String EXTRA_FLIGHTS =
            "com.bc004346.travelus.flights";
    public static final String EXTRA_FLIGHT =
            "com.bc004346.travelus.flight";
    public static final String CANCELLED = "cancelled";
    public static final String DELAYED = "delayed";
    private static final String KEY_FLIGHT = "Flight";
    private Flight mFlight;
    private Runnable mLastUpdatedRunnable = new Runnable() {
        @Override
        public void run() {
            if (mFlight == null) return;

            mLastUpdatedHandler.postDelayed(this, MINUTE);
            Date current = new Date();
            int minutesBack = (int) ((current.getTime() - mLastUpdatedDate.getTime() + 10 * SECOND) / MINUTE);
            String message;
            if (minutesBack < 1)
                message = "Just updated";
            else if (minutesBack < 30)
                message = String.format(mActivity.getString(R.string.flightDetailsLabel_UpdatedXMinutesAgo), minutesBack);
            else if (minutesBack < 60)
                message = "Updated over half an hour ago";
            else if (minutesBack < 180)
                message = "Updated over an hour ago";
            else
                message = "Updated ages ago";
            mLastUpdated.setText(message);
        }
    };
    private Activity mActivity;
    private TextSwitcher mCoachFlightCapacity;
    private TextSwitcher mCoachSeatsAvailable;
    private TextSwitcher mCoachNonRevs;
    private TextSwitcher mFirstFlightCapacity;
    private TextSwitcher mFirstSeatsAvailable;
    private TextSwitcher mFirstNonRevs;
    //private TextView mBoardingPriority;
    private TextView mFlightNumber;
    private TextView mFlightStatus;
    private TextView mLastUpdated;
    private TextView mDeparture;
    private TextView mOriginDestination;
    private TextView mPNR;
    private ProgressBar mProgressBar;
    private TravelUsScreenScraper mTravelUs;
    private long mRefreshInterval = MINUTE;
    private Runnable mTimerRunnable = new Runnable() {
        @Override
        public void run() {
            mRefreshInterval = MINUTE * Long.parseLong(Utility.availabilityRefreshInterval());
            log(String.format(mActivity.getString(R.string.flightDetailsLog_RefreshIntervalIsSet), (int) (mRefreshInterval / 60000)));
            mTimerHandler.postDelayed(this, mRefreshInterval);
            if (Utility.availabilityRefreshEnabled())
                updateFlightDetails(mFlight);
        }
    };
    private Date mLastUpdatedDate = new Date();
    private Handler mTimerHandler = new Handler();
    private Handler mLastUpdatedHandler = new Handler();

    //</editor-fold>

    //<editor-fold desc="Constructor">
    public static FlightDetailsFragment newInstance(Flight flight) {
        Bundle args = new Bundle();
        args.putSerializable(EXTRA_FLIGHT, flight);
        FlightDetailsFragment fragment = new FlightDetailsFragment();
        fragment.setArguments(args);
        return fragment;
    }
    //</editor-fold>

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setRetainInstance(true);

        mFlight = (Flight) getArguments().getSerializable(EXTRA_FLIGHT);

        try {

            mTravelUs = Utility.getInstance().getTravelUS();

            mActivity = getActivity();
            mTimerHandler.postDelayed(mTimerRunnable, mRefreshInterval);
            mLastUpdatedHandler.postDelayed(mLastUpdatedRunnable, MINUTE);
        } catch (Exception e) {
            Utility.log(e.toString());
        }
    }

    @Override
    public void onPause() {
        super.onPause();
        mTimerHandler.removeCallbacks(mTimerRunnable);
        mTimerHandler.removeCallbacks(mLastUpdatedRunnable);
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        try {
            outState.putSerializable(KEY_FLIGHT, mFlight);
        } catch (Exception e) {
            Utility.log(e.toString());
        }
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

        View v = inflater.inflate(R.layout.fragment_flight, null);

        try {
            mPNR = (TextView) v.findViewById(R.id.fragment_flight_pnr);
            mFlightNumber = (TextView) v.findViewById(R.id.fragment_flight_flight_number);
            mDeparture = (TextView) v.findViewById(R.id.fragment_flight_departure_date);
            mOriginDestination = (TextView) v.findViewById(R.id.fragment_flight_origin_destination);
            mFlightStatus = (TextView) v.findViewById(R.id.fragment_flight_status);
            mFirstFlightCapacity = (TextSwitcher) v.findViewById(R.id.fragment_flight_first_capacity);
            mFirstSeatsAvailable = (TextSwitcher) v.findViewById(R.id.fragment_flight_first_sa);
            mFirstNonRevs = (TextSwitcher) v.findViewById(R.id.fragment_flight_first_standby);
            mCoachFlightCapacity = (TextSwitcher) v.findViewById(R.id.fragment_flight_coach_capacity);
            mCoachSeatsAvailable = (TextSwitcher) v.findViewById(R.id.fragment_flight_coach_sa);
            mCoachNonRevs = (TextSwitcher) v.findViewById(R.id.fragment_flight_coach_standby);
            //mBoardingPriority = (TextView) v.findViewById(R.id.fragment_flight_message);
            mProgressBar = (ProgressBar) v.findViewById(R.id.flightDetailsProgressBar);
            mLastUpdated = (TextView) v.findViewById(R.id.flightDetailsLastUpdated);

            ViewSwitcher.ViewFactory viewFactory = new ViewSwitcher.ViewFactory() {
                public View makeView() {
                    TextView myText = new TextView(mActivity);
                    myText.setTextColor(Color.parseColor("#FFFFFF"));
                    //myText.setTextAppearance(mActivity, R.style.BlackFont);
                    myText.setGravity(Gravity.CENTER);
                    return myText;
                }
            };

            mCoachFlightCapacity.setFactory(viewFactory);
            mCoachSeatsAvailable.setFactory(viewFactory);
            mCoachNonRevs.setFactory(viewFactory);
            mFirstFlightCapacity.setFactory(viewFactory);
            mFirstSeatsAvailable.setFactory(viewFactory);
            mFirstNonRevs.setFactory(viewFactory);

            // Declare the in and out animations and initialize them
            Animation in = AnimationUtils.loadAnimation(mActivity, android.R.anim.slide_in_left);
            Animation out = AnimationUtils.loadAnimation(mActivity, android.R.anim.slide_out_right);

            // set the animation type of textSwitcher
            mFirstFlightCapacity.setInAnimation(in);
            mFirstFlightCapacity.setOutAnimation(out);
            mFirstSeatsAvailable.setInAnimation(in);
            mFirstSeatsAvailable.setOutAnimation(out);
            mFirstNonRevs.setInAnimation(in);
            mFirstNonRevs.setOutAnimation(out);
            mCoachFlightCapacity.setInAnimation(in);
            mCoachFlightCapacity.setOutAnimation(out);
            mCoachSeatsAvailable.setInAnimation(in);
            mCoachSeatsAvailable.setOutAnimation(out);
            mCoachNonRevs.setInAnimation(in);
            mCoachNonRevs.setOutAnimation(out);

            if (mFlight != null) setFlight(mFlight);
            updateFlightDetails(mFlight);
        } catch (Resources.NotFoundException e) {
            Utility.log(e.toString());
        }
        return v;
    }

    @Override
    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
        inflater.inflate(R.menu.action_item_menu, menu);
    }

    public void updateFlightDetails(Flight flight) {
        try {
            if (mTravelUs.getIsLoggedIn() && mFlight != null) {
                mLastUpdated.setVisibility(View.INVISIBLE);
                mProgressBar.setVisibility(View.VISIBLE);
                new AsyncTask<Flight, Void, Flight>() {

                    private Exception exception;

                    @Override
                    protected Flight doInBackground(Flight... params) {
                        Flight flight = params[0];
                        try {
                            flight = mTravelUs.checkAvailability(flight);
                        } catch (Exception e) {
                            exception = e;
                        }
                        return flight;
                    }

                    @Override
                    protected void onPostExecute(Flight flight) {
                        if (exception == null) {
                            setFlightAvailability(flight);
                        } else {
                            log(exception, mActivity);
                        }
                    }
                }.execute(flight);
//                new AsyncTask<Flight, Void, Flight>() {
//
//                    private Exception exception;
//
//                    @Override
//                    protected Flight doInBackground(Flight... params) {
//                        Flight flight = params[0];
//                        try {
//                            flight = mTravelUs.checkNonRevList(flight);
//                        } catch (Exception e) {
//                            exception = e;
//                        }
//                        return flight;
//                    }
//
//                    @Override
//                    protected void onPostExecute(Flight flight) {
//                        if (exception == null) {
//                            setFlightNonRevStatus(flight);
//                        } else {
//                            log(exception, mActivity);
//                        }
//                    }
//                }.execute(flight);
                new AsyncTask<Flight, Void, Flight>() {

                    private Exception exception;

                    @Override
                    protected Flight doInBackground(Flight... params) {
                        Flight flight = params[0];
                        try {
                            flight = getFlightStatus(flight);
                        } catch (Exception e) {
                            exception = e;
                        }
                        return flight;
                    }

                    @Override
                    protected void onPostExecute(Flight flight) {
                        mLastUpdated.setVisibility(View.VISIBLE);
                        mProgressBar.setVisibility(View.INVISIBLE);
                        mLastUpdatedDate = new Date();
                        if (exception == null) {
                            setFlightStatus(flight);
                            mLastUpdated.setText("Just updated");
                        } else if (exception.getClass() == TravelUsException.class) {
                            mLastUpdated.setText(exception.getMessage());
                        } else {
                            mLastUpdated.setText(exception.getMessage());
                            log(exception, mActivity);
                        }
                    }
                }.execute(flight);
            }
        } catch (
                Exception e
                )

        {
            log(e.toString());
        }

    }

    private void setFlight(Flight flight) {
        setFlightAvailability(flight);
        //setFlightNonRevStatus(flight);
        setFlightStatus(flight);
    }

    private void setFlightAvailability(Flight flight) {

        try {
            if (mFlight.getPnr() == null) {
                mPNR.setText("");
                mOriginDestination.setText(String.format("%s %s > %s",
                        mFlight.getOrigin(),
                        MILITARY_TIME.format(mFlight.getDeparture()),
                        mFlight.getDestination()));
            } else {
                mPNR.setText(String.format("PNR: %s", mFlight.getPnr()));
                mOriginDestination.setText(String.format("%s %s > %s %s",
                        mFlight.getOrigin(),
                        MILITARY_TIME.format(mFlight.getDeparture()),
                        mFlight.getDestination(),
                        MILITARY_TIME.format(mFlight.getArrival())));
            }

            mFlightNumber.setText(String.format("Flight: %d", mFlight.getFlightNumber()));
            mDeparture.setText(DAY_DATE.format(mFlight.getDeparture()));

            mFirstFlightCapacity.setText(String.valueOf(flight.getFirstClass().getCapacity()));
            mFirstSeatsAvailable.setText(String.valueOf(flight.getFirstClass().getSeatsAvailable()));
            mFirstNonRevs.setText(String.valueOf(flight.getFirstClass().getNonRevsCount()));

            mCoachFlightCapacity.setText(String.valueOf(flight.getCoach().getCapacity()));
            mCoachSeatsAvailable.setText(String.valueOf(flight.getCoach().getSeatsAvailable()));
            mCoachNonRevs.setText(String.valueOf(flight.getCoach().getNonRevsCount()));
        } catch (Exception e) {
            log(e.getMessage());
        }
    }

    //TODO: get priority from Mobile US Airways
//    private void setFlightNonRevStatus(Flight flight) {
//
//        int boardingPriority = flight.getBoardingPriority() - 1;
//        if (boardingPriority >= 0) {
//            Resources r = getResources();
//            String s = r.getQuantityString(R.plurals.flightDetailsMessage_ThereArePeopleAheadOfYou,
//                    boardingPriority, boardingPriority);
//            mBoardingPriority.setText(s);
//        }
//    }

    private void setFlightStatus(Flight flight) {

        mFlightStatus.setText(flight.getFlightStatus());
//        if (flight.getFlightStatus().toLowerCase().equals(DELAYED))
//            mFlightStatus.setBackgroundResource(R.drawable.white_border_orange_background);
//        else if (flight.getFlightStatus().toLowerCase().equals(CANCELLED))
//            mFlightStatus.setBackgroundResource(R.drawable.white_border_red_background);
//        else
//            mFlightStatus.setBackgroundResource(R.drawable.white_border_dark_background);

    }
}
